home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-06-19 | 21.8 KB | 685 lines |
- /*
- * BasicCell.java 1.0 12 Jan 1997
- *
- * Copyright (c) 1996 Krumel & Associates, Inc. All Rights Reserved.
- *
- * This software is provided as is. Krumel & Associates shall not be liable
- * for any damages suffered by licensee as a result of using, modifying or
- * distributing this software or its derivatives.
- */
- package symantec.itools.db.awt;
-
- import java.awt.*;
-
- public class BasicCell implements TableCell, java.awt.image.ImageObserver {
- Grid view;
- DataSource dataSource;
- Coordinate coords;
- boolean selected;
- boolean keyPressedYet;
- boolean loseFocusOnArrow;
- int cursorPos;
- int hlFirst, hlLast; //left & right for highlighting
- boolean selectionMade;
- int offset; //will be used for keeping cursor in cell
- int chopIndex;
- int toLeftOfCell;
- int startX;
- boolean defaultCell;
- int type;
-
- static final int PADSIDES = 5;
-
- public BasicCell(Grid tv, DataSource ds) {
- view = tv;
- dataSource = ds;
- }
-
- public TableCell cloneCell() {
- BasicCell bs = new BasicCell(view, dataSource);
-
- if (coords != null) {
- bs.coords = new Coordinate(coords.row, coords.col);
- }
-
- bs.selected = selected;
- bs.keyPressedYet = keyPressedYet;
- bs.loseFocusOnArrow = loseFocusOnArrow;
- bs.cursorPos = cursorPos;
- bs.selectionMade = selectionMade;
- bs.offset = offset;
- bs.type = type;
-
- return bs;
- }
-
- public int type() {
- return type;
- }
-
- public int type(int t) {
- if (t > CORNER_CELL || t < 0) {
- throw new IllegalArgumentException("Invalid cell type");
- }
-
- return type = t;
- }
-
-
- public void setGrid(Grid v, DataSource ds) {
- view = v;
- dataSource = ds;
- }
-
- public void setDefaultFlag() {
- defaultCell = true;
- }
-
- public void reset() {
- selected = false;
- keyPressedYet = false;
- loseFocusOnArrow = false;
- cursorPos = 0;
- selectionMade = false;
- offset = 0;
- }
-
- public boolean isCellTypeEditable() { return true; }
-
- public void setCoordinates(Coordinate c) {
- coords = c;
- }
-
- public Coordinate getCoordinates() {
- return coords;
- }
-
- public int row() { return coords.row; }
-
- public void setRow(int r) { coords.row = r; }
-
- public int col() { return coords.col; }
-
- public void setCol(int c) { coords.col = c; }
-
- public boolean mouseEvent(Event e) {
- try {
- switch(e.id) {
- case Event.MOUSE_DOWN:
- if (!e.shiftDown()) {
- //if still highlighted position cursor right place and unhighlight
- keyPressedYet= true;
- view.setCapture();
- cursorPos = findCursorPos(e.x);
- selectionMade = false;
- } else {
- //shift pressed so we make a hightlighted region
- hlFirst = cursorPos;
- hlLast = findCursorPos(e.x);
- selectionMade = true;
- }
-
- view.redrawCell(this);
- view.generateEvent(e, view.CELL_MOUSE_DOWN, this);
- break;
-
- case view.CELL_MOUSE_DOUBLE:
- keyPressedYet = false;
- view.redrawCell(this);
- offset = 0;
- view.generateEvent(e, view.CELL_MOUSE_DOUBLE, this);
- break;
-
- case Event.MOUSE_DRAG:
- if (!selectionMade && findCursorPos(e.x) != cursorPos) {
- //select a region
- hlFirst = cursorPos;
- selectionMade = true;
- }
-
- hlLast = cursorPos = findCursorPos(e.x);
- view.redrawCell(this);
- view.generateEvent(e, view.CELL_MOUSE_DRAG, this);
- break;
-
- case Event.MOUSE_UP:
- view.generateEvent(e, view.CELL_MOUSE_UP, this);
- break;
- }
- } catch(DataNotAvailable ex) {
- view.handleException(row(), col(), ex);
- }
-
- return true;
- }
-
- int findCursorPos(int x) throws DataNotAvailable {
- if (x < -offset) {
- return 0;
- }
-
- int total = offset + x;
- FontMetrics fm = view.getCellFontMetrics(this);
- Data data = readData();
- String text = data.toString();
- int len = text.length();
-
- //loop through each letter and determine where cursor goes
- Image im = data.toImage();
- int align = view.getCellAlignment(this);
- if (align == Grid.LEFT) {
- if (offset == 0) {
- total -= PADSIDES + 2;
-
- if (im != null) {
- int imageOffset = im.getWidth(this) + 2;
- int w = view.getColumnWidth(getCoordinates().col);
- int sw = fm.stringWidth(text);
-
- if (imageOffset+sw+2+PADSIDES <= w) {
- total -= imageOffset;
- }
- }
- }
- } else
- if (align == Grid.RIGHT) {
- int sw = fm.stringWidth(text);
- int w = view.getColumnWidth(getCoordinates().col);
- if (sw <= w - PADSIDES*2) {
- total = total - w + sw + PADSIDES;
- }
- } else if (align == Grid.CENTER) {
- int sw = fm.stringWidth(text);
- int w = view.getColumnWidth(getCoordinates().col);
- if (sw<=w) {
- total = total - (w-sw)/2;
- }
- }
-
- //check if all the way to left
- if (total <= 0) { return 0; }
- for(int i=1; i<=len ; i++) {
- if (fm.stringWidth(text.substring(0, i-1) + fm.charWidth(text.charAt(i-1))/2) > total)
- return i;
- }
-
- return len;
- }
-
- public Data getData() throws DataNotAvailable {
- return dataSource.getData(coords);
- }
-
- public Data readData() throws DataNotAvailable {
- return dataSource.readData(coords.row, coords.col);
- }
-
- void deleteChar(Data data) {
- if (cursorPos == 0)
- return;
-
- data.deleteChar(cursorPos);
- cursorPos--;
- }
-
- void deleteSelection(Data data) {
- int hlLeft = Math.min(hlFirst, hlLast);
- int hlRight = Math.max(hlFirst, hlLast);
- for (int i=hlLeft; i<hlRight; i++) {
- data.deleteChar(hlLeft+1);
- }
-
- cursorPos = hlLeft;
- }
-
- public boolean keyEvent(Event e) {
- Data data;
-
- try {
- data = getData();
- } catch (DataNotAvailable ex) {
- view.handleException(row(), col(), ex);
- return true;
- }
-
- char c = (char)e.key;
- boolean changed = false;
- boolean handled = false;
- boolean editable = data.isEditable(coords.row, coords.col)
- && view.getCellEditable(this);
-
- if (!editable && (e.id == e.KEY_ACTION || e.id == e.KEY_PRESS)) {
- return view.generateEvent(e, view.CELL_KEY_DOWN, this);
- } else if (!editable && e.id == e.KEY_RELEASE) {
- return view.generateEvent(e, view.CELL_KEY_UP, this);
- }
-
- if (e.id == e.KEY_ACTION) {
- if (e.shiftDown() && !selectionMade) {
- selectionMade = true;
- hlFirst = hlLast = cursorPos;
- } else if (!e.shiftDown()) {
- selectionMade = false;
- }
-
- switch(c) {
- case e.LEFT:
- if (cursorPos > 0) {
- cursorPos--;
- changed = true;
- }
- break;
- case e.RIGHT:
- if (cursorPos < data.toString().length()) {
- cursorPos++;
- changed = true;
- }
- break;
- case e.UP:
- case e.HOME:
- if (cursorPos != 0) {
- cursorPos = 0;
- changed = true;
- }
- break;
- case e.DOWN:
- case e.END:
- int len = data.toString().length();
- if (cursorPos != len) {
- cursorPos = len;
- changed = true;
- }
- break;
- }
-
- if (selectionMade) hlLast = cursorPos;
- if (changed) {
- view.redrawCell(this);
- }
-
- return view.generateEvent(e, view.CELL_KEY_DOWN, this);
- }
- if (e.id == Event.KEY_PRESS) {
- if (!keyPressedYet) {
- //NEED TO STRIP OUT ANY NON PRINTABLE CHARACTERS!!!
- if (e.key<33 || e.key>122) {
- //not printable so ignore
- return view.generateEvent(e, view.CELL_KEY_DOWN, this);
- }
-
- data.clearText();
- data.appendChar(c);
- keyPressedYet = true;
- view.setCapture();
- cursorPos = 1; //start at beginning
- } else {
- if (selectionMade) {
- deleteSelection(data);
- selectionMade = false;
- //if b.s. or del then delete highlight and return
- if (c == 8 || c == 127) {
- return view.generateEvent(e, view.CELL_KEY_DOWN, this);
- }
- }
-
- if (e.key == 27 /*esc*/) {
- cursorPos = 0;
- keyPressedYet = false;
- handled = view.generateEvent(e, view.UNDO_CELL_EVENT, this);
- } else if (c == 8 /*backspace*/) {
- deleteChar(data);
- handled = view.generateEvent(e, view.CELL_CONTENT_CHANGE, this);
- } else if (c == 10 /*enter*/) {
- try {
- dataSource.commitData();
- } catch(Exception ex) {
- view.handleException(row(), col(), ex);
- }
- } else if (c == 127/*delete*/) {
- if (cursorPos != data.toString().length()) {
- cursorPos++;
- deleteChar(data);
- handled = view.generateEvent(e, view.CELL_CONTENT_CHANGE, this);
- }
- } else if (cursorPos == data.toString().length()) {
- data.appendChar(c);
- cursorPos++;
- handled = view.generateEvent(e, view.CELL_CONTENT_CHANGE, this);
- } else {
- data.insertChar(cursorPos, c);
- cursorPos++;
- }
- }
-
- view.redrawCell(this);
- handled |= view.generateEvent(e, view.CELL_KEY_DOWN, this);
- } else if (e.id == Event.KEY_RELEASE) {
- view.generateEvent(e, view.CELL_KEY_UP, this);
- }
-
- return handled;
- }
-
- public boolean loseFocusOnArrow() {
- return selected & !keyPressedYet;
- }
-
- public void activateCursor() {
- selected = true;
- view.redrawCell(this);
- }
-
- public void deactivateCursor() {
- selected = false;
- view.redrawCell(this);
- }
-
- public boolean canLoseFocus() {
- //try to commit data - if successful then return true
- try {
- //commit dataSource's current data and tell the data to commit
- //also
- dataSource.commitData();
- } catch(Exception ex) {
- //Can throw RuntimeExceptions so catch everything
- view.handleException(row(), col(), ex);
- return false;
- }
-
- return true;
- }
-
- public boolean focusEvent(Event e) {
- if (e.id == Event.GOT_FOCUS) {
- selected = true;
- view.generateEvent(e, view.GOT_CELL_FOCUS, this);
- view.redrawCell(this);
- } else {
- selected = false;
- keyPressedYet = false;
- selectionMade = false;
- offset = 0;
- cursorPos = 0;
- view.generateEvent(e, view.LOST_CELL_FOCUS, this);
- try {
- dataSource.commitData();
- } catch(Exception ex) {
- view.handleException(row(), col(), ex);
- }
- view.redrawAroundCell(this);
- }
-
- return true;
- }
-
- public boolean actionEvent(Event e) {
- keyPressedYet = false;
- view.redrawCell(this);
- offset = 0;
- return true;
- }
-
- public void drawCell(Graphics g, CellHints hints) {
- Data data;
-
- try {
- data = readData();
- } catch (DataNotAvailable ex) {
- view.handleException(row(), col(), ex);
- data = new ImageStringData(dataSource, "");
- }
-
- Rectangle r = hints.bounds();
- FontMetrics fm = view.getCellFontMetrics(this);
- int asc = fm.getAscent() + 1;
- int sw = fm.stringWidth(data.toString());
- int imageOffset = 0;
- Color oldfg = hints.fg;
- int origX = r.x,
- origWidth = r.width;
-
- hints.setBackground(g);
- g.fillRect(r.x, r.y, r.width-1, r.height-1);
- Image im = data.toImage();
- switch(hints.alignment()) {
- case Grid.LEFT:
- if (im != null) {
- imageOffset = im.getWidth(this) + 2;
- }
-
- //check to see if it will all fit within cell
- if (imageOffset+sw+2+PADSIDES <= r.width && im != null) {
- r.x += PADSIDES;
- r.y += 1;
- g.drawImage(im, r.x, r.y, this);
- r.y -= 1;
- } else {
- imageOffset = 0;
- }
-
- r.x = origX + imageOffset + PADSIDES;
- break;
- case Grid.CENTER:
- if (sw>(r.width - PADSIDES*2)) {
- r.x += PADSIDES;
- } else {
- r.x = r.x + (r.width-sw)/2;
- }
- break;
- case Grid.RIGHT:
- if (im != null) {
- imageOffset = im.getWidth(this);
- }
- //the 3 is just a fudge factor - there must be a better way!!!!
- //check to see if it will all fit within cell
- if ((imageOffset+2+sw+PADSIDES*2+3) <= r.width && im != null) {
- r.x = r.x + r.width - sw - imageOffset - 2 - PADSIDES - 3;
- r.y += 1;
- g.drawImage(im, r.x, r.y, this);
- r.y -= 1;
- r.x = origX + r.width - sw - PADSIDES - 3;
- } else {
- imageOffset = 0;
- if (sw>(r.width - PADSIDES*2)) {
- r.x += PADSIDES;
- } else {
- r.x = origX + r.width - sw - PADSIDES - 3;
- }
- }
- break;
- }
-
- hints.setForeground(g);
- r.width = r.width + origX - r.x - PADSIDES;
- startX = r.x;
- drawText(data, g, r, fm, hints);
- r.width = origWidth;
-
- //draw cursor
- if (selected && keyPressedYet) {
- int cpos = 0;
- if (data.toString().length() > 0) {
- cpos = fm.stringWidth(data.subString(toLeftOfCell, cursorPos));
- }
- g.drawLine(r.x + cpos,
- r.y + 2,
- r.x + cpos,
- r.y + fm.getHeight());
- }
-
-
- r.x = origX;
-
- hints.drawBoundary(g);
- //The new way is slower but more flexible - some future enhancements to the
- //drawing algorithms in the Grid class should make the slowdown
- //insignificant soon enough.
- // g.setColor(Color.gray);
- // g.drawRect(r.x, r.y, r.width-1, r.height-1);
- // g.setColor(oldfg);
- }
-
- protected String chopString(Data data, Rectangle r, FontMetrics fm) {
- String text = data.toString();
- int w = view.getColumnWidth(coords.col);
- chopIndex = 1;
- String t;
-
- if (text.length() == 0) {
- return text;
- }
- //chop off any part of string not visible
- setOffset(text, r, fm);
- if (offset != 0) {
- int left;
- while(toLeftOfCell < text.length()) {
- left = fm.stringWidth(text.substring(0, toLeftOfCell));
- if (left < offset + PADSIDES) {
- toLeftOfCell++;
- } else {
- toLeftOfCell--;
- break; //found the visible portion of the text
- }
- }
-
- toLeftOfCell -= (toLeftOfCell < text.length()) ?0 :1;
- text = text.substring(toLeftOfCell, text.length());
- } else {
- toLeftOfCell = 0;
- }
-
- //get the portion of string that fits into cell
- do {
- t = text.substring(0, chopIndex);
- } while(fm.stringWidth(t) < w - PADSIDES*2 && chopIndex++ < text.length());
-
- return text.substring(0, --chopIndex);
- }
-
- protected void drawText(Data data, Graphics g, Rectangle r,
- FontMetrics fm, CellHints hints)
- {
- //all highlighted and ready for delete
- String text = chopString(data, r, fm);
-
- if (selected && !keyPressedYet) {
- hints.setForeground(g);
- g.fillRect(r.x-1,
- r.y+3,
- fm.stringWidth(text.toString())+4,
- fm.getHeight()-1);
- hints.setBackground(g);
- g.drawString(text, r.x, r.y+fm.getAscent()+2);
- } else if (selected && !selectionMade) {
- //draw string with cursor
- g.drawString(text, r.x, r.y+fm.getAscent()+2);
- } else if(!selected || !selectionMade ) {
- //no highlight
- g.drawString(text, r.x, r.y+fm.getAscent()+2);
- } else {
- //some section must be highlighted
- int hlLeft = Math.min(hlFirst, hlLast);
- int hlRight = Math.max(hlFirst, hlLast);
- hlRight = Math.min(hlRight, chopIndex);
-
- if (toLeftOfCell != 0) {
- hlLeft = Math.max(hlFirst, toLeftOfCell);
- }
- String t = text.substring(0, hlLeft);
-
- //draw first unselected portion
- g.drawString(t, r.x, r.y+fm.getAscent()+2);
-
- //draw middle selected portion
- int pixelHLStart = fm.stringWidth(t) + r.x - offset;
- t = text.substring(hlLeft, hlRight);
- int pixelHLStop = fm.stringWidth(t) + pixelHLStart;
- hints.setForeground(g);
- g.fillRect(pixelHLStart,
- r.y+2,
- pixelHLStop - pixelHLStart,
- fm.getHeight()-1);
- hints.setBackground(g);
- g.drawString(t, pixelHLStart, r.y+fm.getAscent()+2);
-
- //draw end unselected portion
- hints.setForeground(g);
- t = text.substring(hlRight, text.length());
- g.drawString(t, pixelHLStop, r.y+fm.getAscent()+2);
- }
- }
-
- void setOffset(String text, Rectangle r, FontMetrics fm) {
- String sub = text.substring(0, cursorPos);
- int toCursor = fm.stringWidth(sub);
- int fudge = 3;
-
- if (!selected) {
- offset = 0;
- return;
- }
-
- if (toCursor > r.width - fudge) {
- offset = -r.width + toCursor + fudge;
- } else {
- offset = 0;
- }
- }
-
- int textLeft(int txtWidth, Rectangle r) {
- switch(view.getCellAlignment(this)) {
- case Grid.CENTER:
- if (txtWidth>r.width) {
- return r.x;
- } else {
- return r.x + (r.width-txtWidth)/2;
- }
- case Grid.RIGHT:
- if (txtWidth>r.width) {
- return r.x + PADSIDES;
- } else {
- return r.x + r.width - txtWidth - PADSIDES;
- }
- case Grid.LEFT:
- default:
- return r.x + PADSIDES;
- }
- }
-
- /**
- * Repaints the list when the cell's image has changed.
- * @return true if image has changed; false otherwise.
- */
- public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
- if ((flags & (ABORT|ERROR)) != 0) {
- return false;
- }
-
- if ((flags & ALLBITS) != 0) {
- view.redrawAsync();
- return false;
- } else {
- return true;
- }
- }
-
- public String toString() {
- try {
- return readData().toString();
- } catch(DataNotAvailable ex) {
- return "ERROR getting data";
- }
- }
-
- public String stats() {
- try {
- return "BasicCell: row=" + coords.row + " col=" + coords.col +
- " text=" + readData().toString();
- } catch(DataNotAvailable ex) {
- return "BasicCell: row=" + coords.row + " col=" + coords.col +
- " could not retrieve data";
- }
- }
- }
-
-